package com.decent.core.alarm.util;

import cn.hutool.core.lang.Opt;
import cn.hutool.json.JSONUtil;
import com.decent.common.bo.MessageBean;
import com.decent.common.enums.CommonStatusEnum;
import com.decent.common.enums.alarm.AlarmTypeEnum;
import com.decent.common.exception.ErrorCodeException;
import com.decent.common.util.BeanUtils;
import com.decent.core.alarm.dao.AlarmCoreDao;
import com.decent.core.alarm.model.AlarmModel;
import com.decent.core.alarm.process.AlarmProcessContext;
import com.decent.core.alarm.process.AlarmProcessExecutor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.Optional;
import java.util.function.Supplier;

/**
 * 钉钉报警工具类
 *
 * @author menghx
 * @date 2022-03-31
 */
@Slf4j
@Data
public class DingDingAlarmUtil {
    /**
     * 报警配置sql管理器
     */
    private static AlarmCoreDao alarmCoreDao;
    /**
     * 报警执行器
     */
    private static AlarmProcessExecutor alarmProcessExecutor;

    /**
     * 发送钉钉消息
     *
     * @param alarmModel 发送消息内容
     */
    public static void sendMsg(AlarmModel alarmModel) {
        try {
            //获取流程处理控制器
            //获取流程处理控制器
            AlarmProcessExecutor alarmProcessExecutor = Optional.ofNullable(DingDingAlarmUtil.alarmProcessExecutor).orElseGet(() -> {
                AlarmProcessExecutor bean = BeanUtils.getBean(AlarmProcessExecutor.class);
                DingDingAlarmUtil.alarmProcessExecutor = bean;
                return bean;
            });
            // 处理发送请求
            AlarmProcessContext context = alarmProcessExecutor.process(AlarmProcessContext.builder()
                    // 默认不中断流程,若处理流程中出现异常则该字段被替换为true
                    .needBreak(false)
                    .processModel(alarmModel)
                    // 处理成功时的响应,若处理流程中出现异常则该响应被替换
                    .response(MessageBean.success()).build());
            String msg = Opt.ofNullable(context.getResponse()).map(MessageBean::getMessage).get();
            log.info("发送钉钉报警,响应[{}],请求[{}]", msg, JSONUtil.toJsonStr(alarmModel));
        } catch (Exception e) {
            log.warn("发送钉钉报警未知异常,sendMsgModel[{}]", JSONUtil.toJsonStr(alarmModel), e);
        }
    }

    /**
     * 发送钉钉消息,未开启模板则不执行supplier.get()
     *
     * @param alarmType 发送消息类型
     * @throws ErrorCodeException 模板未开启异常
     */
    public static void sendMsg(AlarmTypeEnum alarmType, Supplier<AlarmModel> supplier) {
        try {
            AlarmCoreDao alarmCoreDao = Optional.ofNullable(DingDingAlarmUtil.alarmCoreDao).orElseGet(() -> {
                AlarmCoreDao bean = BeanUtils.getBean(AlarmCoreDao.class);
                DingDingAlarmUtil.alarmCoreDao = bean;
                return bean;
            });
            // 校验是否开启模板
            Opt.ofNullable(alarmCoreDao.queryTemplate(alarmType, CommonStatusEnum.NORMAL)).orElseThrow(ErrorCodeException::new, String.format("[%s]模板未开启", alarmType));
            //获取流程处理控制器
            AlarmProcessExecutor alarmProcessExecutor = Optional.ofNullable(DingDingAlarmUtil.alarmProcessExecutor).orElseGet(() -> {
                AlarmProcessExecutor bean = BeanUtils.getBean(AlarmProcessExecutor.class);
                DingDingAlarmUtil.alarmProcessExecutor = bean;
                return bean;
            });
            // 处理发送请求
            AlarmProcessContext context = alarmProcessExecutor.process(AlarmProcessContext.builder()
                    // 默认不中断流程,若处理流程中出现异常则该字段被替换为true
                    .needBreak(false)
                    .processModel(supplier.get())
                    // 处理成功时的响应,若处理流程中出现异常则该响应被替换
                    .response(MessageBean.success()).build());
            String msg = Opt.ofNullable(context.getResponse()).map(MessageBean::getMessage).get();
            log.info("发送钉钉报警,响应[{}]", msg);
        } catch (Exception e) {
            log.warn("发送钉钉报警未知异常[{}]", alarmType, e);
        }
    }

}
